/**
 * 
 */
package wpmp.security.mgr.web;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.struts2.convention.annotation.Action;
import org.apache.struts2.convention.annotation.Result;
import org.apache.struts2.convention.annotation.Results;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.support.rowset.SqlRowSet;

import wcommons.lang.NumberUtils;
import wpmp.extjs3.ExtjsUtils;
import wpmp.extjs3.data.Form;
import wpmp.extjs3.data.JsonStore;
import wpmp.extjs3.data.TreeNode;
import wpmp.security.client.utils.UserUtils;
import wpmp.security.mgr.Statics;
import wpmp.security.mgr.base.BaseAction;
import wpmp.security.mgr.base.DefaultBaseAction;
import wpmp.security.mgr.entity.Role;
import wpmp.security.mgr.entity.User;
import wpmp.security.mgr.pub.OrgUtils;
import wpmp.security.mgr.service.RoleService;
import wpmp.security.mgr.service.UserService;

/**
 * @author Wayne.Wang<5waynewang@gmail.com>
 * @since 7:59:02 PM Mar 15, 2013
 */
@Action("user")
@Results({ @Result(name = BaseAction.LIST, location = "/WEB-INF/user/list.jsp"),
		@Result(name = BaseAction.INPUT, location = "/WEB-INF/user/input.jsp"),
		@Result(name = BaseAction.VIEW, location = "/WEB-INF/user/view.jsp"),
		@Result(name = UserAction.LIST_ROLE, location = "/WEB-INF/user/listRole.jsp") })
public class UserAction extends DefaultBaseAction<User> {

	private static final long serialVersionUID = 1L;

	private static final Logger LOG = LoggerFactory.getLogger(UserAction.class);

	public static final String LIST_ROLE = "listRole";

	@Autowired
	private RoleService roleService;
	@Autowired
	private UserService service;

	static final String[] ignoreProperties = { "password" };

	public void listJSON() throws Exception {
		final int total = service.count(entity);
		if (total == 0) {
			this.renderJson(JsonStore.EMPTY.toJSONString());
			return;
		}

		final List<User> users = service.list(entity, page);
		final List<User> records = new LinkedList<User>();
		for (User user : users) {
			final User record = new User();
			// 屏蔽一些信息，如：密码
			BeanUtils.copyProperties(user, record, ignoreProperties);

			record.setOrgName(OrgUtils.getOrgNameDefaultUngrouped(record.getOrgId()));
			record.setCreateUserName(UserUtils.getUserName(record.getCreateUser()));
			record.setUpdateUserName(UserUtils.getUserName(record.getUpdateUser()));

			records.add(record);
		}

		this.renderJson(new JsonStore<User>(total, records).toJSONString());
	}

	@Override
	public String input() throws Exception {
		return INPUT;
	}

	public void getJSON() throws Exception {
		final User result = service.get(entity.getId());

		if (LOG.isDebugEnabled()) {
			LOG.debug("{}", result);
		}

		if (result == null) {
			LOG.warn("can not found User by id[{}]", entity.getId());

			this.renderJson(ExtjsUtils.getDefaultErrorFormJSONString(Statics.DEFAULT_ERROR_MSG));
			return;
		}

		result.setPassword(null);
		result.setOrgName(OrgUtils.getOrgNameDefaultUngrouped(result.getOrgId()));

		this.renderJson(Form.newInstance(result).toJSONString());
	}

	public void viewJSON() throws Exception {
		final User result = service.get(entity.getId());

		if (LOG.isDebugEnabled()) {
			LOG.debug("{}", result);
		}

		if (entity == null) {
			LOG.warn("can not found User by id[{}]", entity.getId());

			this.renderJson(ExtjsUtils.getDefaultErrorFormJSONString(Statics.DEFAULT_ERROR_MSG));
			return;
		}

		result.setPassword(null);
		result.setOrgName(OrgUtils.getOrgNameDefaultUngrouped(result.getOrgId()));
		result.setCreateUserName(UserUtils.getUserName(result.getCreateUser()));
		result.setUpdateUserName(UserUtils.getUserName(result.getUpdateUser()));

		this.renderJson(Form.newInstance(result).toJSONString());
	}

	public void insertJSON() throws Exception {
		if (!UserUtils.isAdmin(this.getRequest())) {
			// 非管理员不能创建管理人员
			entity.setIsAdmin(Boolean.FALSE);
		}

		this.renderJson(service.insert(entity).toJSONString());
	}

	public void updateJSON() throws Exception {
		if (!UserUtils.isAdmin(this.getRequest())) {
			// 非管理员不能创建管理人员
			entity.setIsAdmin(Boolean.FALSE);
		}

		this.renderJson(service.update(entity).toJSONString());
	}

	public void deleteJSON() throws Exception {
		this.renderJson(service.delete(entity).toJSONString());
	}

	/**
	 * 重置密码
	 */
	public void resetPasswordJSON() {
		this.renderJson(service.resetPassword(entity).toJSONString());
	}

	/**
	 * 授权角色
	 * 
	 * @throws Exception
	 */
	public void addRoleJSON() throws Exception {
		if (ArrayUtils.isNotEmpty(entity.getIds())) {
			this.renderJson(service.addRole(entity.getIds(), entity.getRoleIds()).toJSONString());
		}
		else {
			this.renderJson(service.resetRole(entity.getId(), entity.getRoleIds()).toJSONString());
		}
	}

	public String listRole() throws Exception {
		return LIST_ROLE;
	}

	/**
	 * 获取授权角色，默认选中已经授权的角色
	 * 
	 * @throws Exception
	 */
	public void listRoleJSON() throws Exception {
		if (!NumberUtils.gtZero(entity.getId())) {
			LOG.warn("userId is null");
			this.renderJson("[]");
			return;
		}
		final List<TreeNode> treeNodes = getTreeNodes();
		setTreeNodeChecked(treeNodes, roleService.listByUserId(entity.getId()));

		final String jsonString = TreeNode.toJSONString(treeNodes);

		if (LOG.isDebugEnabled()) {
			LOG.debug(jsonString);
		}

		this.renderJson(jsonString);
	}

	/**
	 * 设置节点选中
	 * 
	 * @param nodes
	 * @param checkedRoleList
	 */
	private void setTreeNodeChecked(List<TreeNode> nodes, List<Role> checkedRoleList) {
		if (checkedRoleList == null || checkedRoleList.isEmpty()) {
			return;
		}
		// 需要选中的角色
		StringBuilder opttype;
		Map<Long, StringBuilder> roleOpttypeMap = new HashMap<Long, StringBuilder>();
		for (TreeNode treeNode : nodes) {
			boolean checked = false;
			for (Role checkedRole : checkedRoleList) {
				if (checkedRole.getId().toString().equals(treeNode.getId())) {
					opttype = roleOpttypeMap.get(checkedRole.getId());
					if (opttype != null && opttype.length() > 0) {
						treeNode.setText(opttype.insert(0, treeNode.getText()).toString());
					}
					checked = true;
					break;
				}
			}
			treeNode.addAttribute("checked", checked);
			boolean expanded = false;
			for (Role checkedRole : checkedRoleList) {
				if (!checkedRole.getLevel().equals(treeNode.getAttributes().get("level"))
						&& checkedRole.getLevel().startsWith((String) treeNode.getAttributes().get("level"))) {
					expanded = true;
					break;
				}
			}
			treeNode.addAttribute("expanded", expanded);
		}
	}

	/**
	 * 获取所有节点
	 * 
	 * @return
	 */
	@SuppressWarnings("unchecked")
	private List<TreeNode> getTreeNodes() {
		final HttpServletRequest req = this.getRequest();

		Long roleId = entity.getRoleId();
		if (!NumberUtils.gtZero(roleId)) {
			String node = req.getParameter("node");
			if (StringUtils.isNotBlank(node)) {
				roleId = Long.valueOf(node);
			}
		}
		if (!NumberUtils.gtZero(roleId)) {
			roleId = Statics.ROOT_ID;// root 节点
		}
		final List<Role> children = roleService.getChildren(roleId);
		if (CollectionUtils.isEmpty(children)) {
			return Collections.EMPTY_LIST;
		}

		final SqlRowSet rs = roleService.queryChildrenIsLeaf(roleId);
		final List<TreeNode> treeNodes = new ArrayList<TreeNode>();
		for (Role child : children) {
			final TreeNode treeNode = new TreeNode();
			treeNode.setId(child.getId().toString());
			treeNode.setText(child.getName());

			boolean isLeaf = false;
			while (rs.next()) {
				if (NumberUtils.eq(child.getId(), rs.getLong("id"))) {
					isLeaf = rs.getBoolean("is_leaf");
				}
			}
			rs.beforeFirst();
			treeNode.setLeaf(isLeaf);
			treeNode.addAttribute("orderNum", child.getOrderNum());
			treeNode.addAttribute("level", child.getLevel());
			treeNodes.add(treeNode);
		}
		return treeNodes;
	}

	/**
	 * 授权角色
	 * 
	 * @throws Exception
	 */
	public void resetRoleJSON() throws Exception {
		this.renderJson(service.resetRole(entity.getId(), entity.getRoleIds()).toJSONString());
	}

	@Override
	public User getModel0() {
		if (entity == null) {
			entity = new User();
		}
		return entity;
	}
}
